#include "lvgl/lvgl.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include "lv_drivers/display/sunxifb.h"
#include <unistd.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include "pthread.h"
#include "lv_demos.h"

#include "lv_page_main.h"

#define DISP_BUF_SIZE (480 * 480)

lv_ft_info_t font_info_72;
lv_ft_info_t font_info_40;
lv_ft_info_t font_info_20;

void lv_load_font(void)
{
    font_info_72.name   = "/AlibabaPuHuiTi-3-55-Regular.ttf";
    font_info_72.weight = 72;
    font_info_72.style  = FT_FONT_STYLE_NORMAL;
    font_info_72.mem    = NULL;
    lv_ft_font_init(&font_info_72);

    font_info_40.name   = "/AlibabaPuHuiTi-3-55-Regular.ttf";
    font_info_40.weight = 40;
    font_info_40.style  = FT_FONT_STYLE_NORMAL;
    font_info_40.mem    = NULL;
    lv_ft_font_init(&font_info_40);

    font_info_20.name   = "/AlibabaPuHuiTi-3-55-Regular.ttf";
    font_info_20.weight = 20;
    font_info_20.style  = FT_FONT_STYLE_NORMAL;
    font_info_20.mem    = NULL;
    lv_ft_font_init(&font_info_20);
}

int main(int argc, char * argv[])
{
    setenv("TZ", "Asia/Shanghai", 1);

    /*LittlevGL init*/
    lv_init();

    //    /*Linux frame buffer device init*/
    //    fbdev_init();
    //
    //    /*A small buffer for LittlevGL to draw the screen's content*/
    //    static lv_color_t buf[DISP_BUF_SIZE];
    //
    //    /*Initialize a descriptor for the buffer*/
    //    static lv_disp_draw_buf_t disp_buf;
    //    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    uint32_t rotated = LV_DISP_ROT_NONE;

    /*Linux frame buffer device init*/
    sunxifb_init(rotated);

    /*A buffer for LittlevGL to draw the screen's content*/
    static uint32_t width, height;
    sunxifb_get_sizes(&width, &height);

    static lv_color_t * buf;
    buf = (lv_color_t *)sunxifb_alloc(width * height * sizeof(lv_color_t), "lv_examples");

    if(buf == NULL) {
        sunxifb_exit();
        printf("malloc draw buffer fail\n");
        return 0;
    }

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, width * height);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &disp_buf;
    disp_drv.flush_cb = sunxifb_flush;
    disp_drv.hor_res  = (lv_coord_t)width;
    disp_drv.ver_res  = (lv_coord_t)height;
    disp_drv.rotated  = rotated;
    lv_disp_drv_register(&disp_drv);

    evdev_init();
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;
    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb      = evdev_read;
    lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv_1);

    //    /*Set a cursor for the mouse*/
    //    LV_IMG_DECLARE(mouse_cursor_icon)
    //    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    //    lv_img_set_src(cursor_obj, &mouse_cursor_icon);      /*Set the image source*/
    //    lv_indev_set_cursor(mouse_indev, cursor_obj);        /*Connect the image  object to the driver*/

        lv_demo_widgets();

//    lv_demo_benchmark_set_max_speed(true);
//    lv_demo_benchmark();

    while(1) {
        lv_timer_handler();
        usleep(5000);
    }
    sunxifb_free((void **)&buf, "lv_examples");
    sunxifb_exit();
    return 0;
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}
